﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using System.Configuration;
using System.Data;
using System.Resources;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Net.Mail;
using System.Net;

namespace MSBIHelper.Helper
{

    public static class ExceptionHandler
    {
        // Handle the UI exceptions by showing a dialog box, and asking the user whether
        // or not they wish to abort execution.
        public static void UIThreadException(object sender, ThreadExceptionEventArgs t)
        {
            DialogResult result = DialogResult.Cancel;
            try
            {
                result = ShowThreadExceptionDialog("Windows Forms Error", t.Exception);
            }
            catch
            {
                try
                {
                    MessageBox.Show("Fatal Windows Forms Error",
                        "Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
                }
                finally
                {
                    Application.Exit();
                }
            }

            // Exits the program when the user clicks Abort.
            if (result == DialogResult.Abort)
                Application.Exit();
        }
 
        // Handle the UI exceptions by showing a dialog box, and asking the user whether
        // or not they wish to abort execution.
        // NOTE: This exception cannot be kept from terminating the application - it can only 
        // log the event, and inform the user about it. 
        public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                Exception ex = (Exception)e.ExceptionObject;
                string errorMsg = "An application error occurred. Please contact the adminstrator " +
                    "with the following information:\n\n";

                // Since we can't prevent the app from terminating, log this to the event log.
                if (!EventLog.SourceExists("ThreadException"))
                {
                    EventLog.CreateEventSource("ThreadException", "Application");
                }

                // Create an EventLog instance and assign its source.
                EventLog myLog = new EventLog();
                myLog.Source = "ThreadException";
                myLog.WriteEntry(errorMsg + ex.Message + "\n\nStack Trace:\n" + ex.StackTrace);
            }
            catch (Exception exc)
            {
                try
                {
                    MessageBox.Show("Fatal Non-UI Error",
                        "Fatal Non-UI Error. Could not write the error to the event log. Reason: "
                        + exc.Message, MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    Util.SendSmtpEmail("xiao-hua.yao@hp.com","exception of msbihelper",
                        "msg:" + exc.Message + Environment.NewLine
                        + "Detail:" + exc.StackTrace
                        );
                }
                finally
                {
                    Application.Exit();
                }
            }
        }

        // Creates the error message and displays it.
        public static DialogResult ShowThreadExceptionDialog(string title, Exception e)
        {
            string errorMsg = "An application error occurred. Please contact the adminstrator " +
                "with the following information:\n\n";
            errorMsg = errorMsg + e.Message;
            Util.SendSmtpEmail("xiao-hua.yao@hp.com", "exception info of msbihelper",
                "Msg:" + e.Message + Environment.NewLine
                + "Statcktrace:" + e.StackTrace);
            return MessageBox.Show(errorMsg, title, MessageBoxButtons.AbortRetryIgnore,
                MessageBoxIcon.Stop);
        }
    }

    public delegate void MsgDlg(object sender,object msg);

    public class MidModule
    {
        public static event MsgDlg EventSend;
        public static void SendMessage(object sender, object msg)
        {
            if (EventSend != null)//
            {
                EventSend(sender, msg);
            }
        }
    }
    
    public static class RfcWriter
    { 

        public static void WriteDataTable(DataTable sourceTable, TextWriter writer, bool includeHeaders)
        {
            if (includeHeaders)
            {
                List<string> headerValues = new List<string>();
                foreach (DataColumn column in sourceTable.Columns)
                {
                    headerValues.Add(QuoteValue(column.ColumnName));
                }

                writer.WriteLine(String.Join(",", headerValues.ToArray()));
            }

            string[] items = null;
            foreach (DataRow row in sourceTable.Rows)
            {
                items = row.ItemArray.Select(o => QuoteValue(o.ToString())).ToArray();
                writer.WriteLine(String.Join(",", items));
            }

            writer.Flush();
        }

        private static string QuoteValue(string value)
        {
            return String.Concat("\"", value.Replace("\"", "\"\""), "\"");
        }
    } 

    public static class SSASHelper
    {
        public static string QuoteName(this String str)
        {
            return "[" + str + "]";
        }
        public static string AppendComma(this String str)
        {
            return str + ",";
        }
        public static string AppendNewLine(this String str)
        {
            return str + "\r\n";
        }
        public static string ReplaceFirstUnderLineWithDot(this String str)
        {
            int cindex = str.IndexOf('_');
            if (cindex == -1) return str;
            return str.Substring(0, cindex) + "." + str.Substring(cindex + 1);
        }
        public static string ReplaceDotWithUnderLine(this String str)
        {
            return str.Replace(".", "_");
        }
        public static string RemoveTableSchema(this String str)
        {
            //datasource schema is schemaname_tablename.columnname
            //sometimes maybe there is no schema
            int cindex = str.IndexOf('_');
            if (cindex == -1) return str;
            return str.Substring(cindex + 1);
        }

        public static string AppendLeftParenthesis(this String str)
        {
            return str + "(";
        }
        public static string AppendRightParenthesis(this String str)
        {
            return str + ")";
        }
        public static string Append(this String str, string value)
        {
            return str + value;
        }

    }

    public class ParameterObject
    {
       public bool _isAdd{get;set;}
       public bool _isFolder { get;set;}
       public RichTextBox _rtb { get;set;}
       public string _varNameValue {get;set; }
       public string[] _fileNames { get;set;}
       public string _fileName {get;set; }
       public ParameterObject() { }
 
    }
 
    class Util
    {
      static  FolderBrowserDialog fbd1 = new FolderBrowserDialog();
      static  OpenFileDialog ofd1 = new OpenFileDialog();
      static  ManualResetEvent mreofd = new ManualResetEvent(false);
      static ResourceManager _rm = new ResourceManager(typeof(MyResource));

      public static void SetDgvColumnWidth(DataGridView dataGridView1)
      {
          //Adjus the colume width automatically
          int Width = 0;
          for (int I = 0; I < dataGridView1.ColumnCount; I++)
          {
              DataGridViewColumn column = dataGridView1.Columns[I];
              column.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
              Width = dataGridView1.Columns[I].Width;
              column.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
              dataGridView1.Columns[I].Width = Width;
          }
      }

      public static void RunCmd(string scmd)
      {
          System.Diagnostics.Process.Start("explorer", scmd);
      }

      public static string[] SelectFiles(bool isFolder)
        {
            object filenames = new string[] { };
            mreofd.Reset();
            Thread thread = new Thread(
                o =>
                {
                    if (isFolder)
                        getFolderFiles(ref filenames);
                    else
                        getFiles(ref filenames);
                }
                );
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            mreofd.WaitOne();
            return (string[])filenames;
        }

       static void getFolderFiles(ref Object obj)
        {
            string pkgfolder = string.Empty;
            if (fbd1.ShowDialog().Equals(DialogResult.OK))
            {
                pkgfolder = fbd1.SelectedPath;
                obj = Directory.GetFiles(pkgfolder, "*.dtsx", SearchOption.AllDirectories);
            }
            mreofd.Set();
        }

       static void getFiles(ref Object obj)
        {
            ofd1.Multiselect = true;
            if (ofd1.ShowDialog().Equals(DialogResult.OK))
            {
                obj = ofd1.FileNames;
            }
            mreofd.Set();
        }

       public static void work(bool isAdd, bool isFolder,RichTextBox rtbMsg,DoGoodJob dgj)
       {
           string[] filenames = SelectFiles(isFolder);
           if (filenames.Length == 0) return;
           Thread workThread = new Thread(e =>
           {
               ParallelHelper.ParallelDoJob(filenames, isAdd, rtbMsg,dgj);
           }
           );
           workThread.Name = "workThread";
           workThread.Priority = ThreadPriority.AboveNormal;
           workThread.Start();
       }

       public static void work(ParameterObject _po, DoGoodJob2 dgj)
       {
           _po._fileNames = SelectFiles(_po._isFolder);
           if (_po._fileNames.Length == 0) return;
           Thread workThread = new Thread(e =>
           { 
               ParallelHelper.ParallelDoJob(_po, dgj);
           }
           );
           workThread.Name = "workThread";
           workThread.Priority = ThreadPriority.AboveNormal;
           workThread.Start();
       }

       public static void HeightErrorFileList(RichTextBox rtb)
       {
            string Sstart = "Error files list:";
            string Send = "*********************************************************$";
            int start = rtb.Text.IndexOf(Sstart);
            int len = rtb.Text.IndexOf(Send) - start;
            rtb.Select(start, len);
            rtb.SelectionColor = Color.Red;
            rtb.SelectionFont = new Font(rtb.Font, rtb.Font.Style | FontStyle.Bold | FontStyle.Italic);
            rtb.SelectionBackColor = Color.Yellow;
       }


       public static DataTable GetAppSetting()
       {
           DataTable dt = new DataTable();
           dt.Columns.Add("Key");
           dt.Columns.Add("Value");
           Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
           AppSettingsSection AppSettingSec = config.AppSettings;
           foreach (KeyValueConfigurationElement item in AppSettingSec.Settings)
           {
               if (item.LockItem != true)
               {
                   DataRow dr = dt.NewRow();
                   dr[0] = item.Key;
                   dr[1] = item.Value;
                   dt.Rows.Add(dr);
               }
           }
           return dt;
       }

       public static void UpdateAppSetting(DataGridView dgv)
       {
           Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
           AppSettingsSection AppSettingSec = config.AppSettings;
           foreach (DataGridViewRow dgvr in dgv.Rows)
           {
               if (AppSettingSec.Settings[dgvr.Cells[0].Value.ToString()].Value != dgvr.Cells[1].Value.ToString())
                   AppSettingSec.Settings[dgvr.Cells[0].Value.ToString()].Value  = dgvr.Cells[1].Value.ToString();
           }
           ConfigurationManager.RefreshSection("appSettings");
           config.Save();
       }

       public static string GetAppSetting(string key)
       {
               return ConfigurationManager.AppSettings[key];
       }

       public static string GetStringFromResource(string sourceName)
       {
           return _rm.GetString(sourceName);
       }

       public static void GetUserManul()
       {
           string target = "http://www.kuaipan.cn/file/id_7224998280305156.htm";  

           try
           {
               System.Diagnostics.Process.Start(target);
           }
           catch
               (System.ComponentModel.Win32Exception noBrowser)
           {
               if (noBrowser.ErrorCode == -2147467259)
                   MessageBox.Show(noBrowser.Message);
           }
           catch (System.Exception other)
           {
               MessageBox.Show(other.Message);
           }
       }

       public static void Explorer(string path)
       {
           Process process = new Process
           {
               StartInfo = { FileName = "explorer.exe", Arguments = path }
           };
           process.Start();
           process.WaitForExit();
           process.Close();
       }

       public void GetFileCount(object para)
       {
           string path = para.ToString().Split(new char[] { ',' })[0];
           int pos = int.Parse(para.ToString().Split(new char[] { ',' })[1]);
           int num2 = int.Parse(para.ToString().Split(new char[] { ',' })[2]);
           int num3 = int.Parse(para.ToString().Split(new char[] { ',' })[3]);
           int num4 = 0;
           using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
           {
               int count = 0x100000 * num3;
               byte[] buffer = new byte[count];
               int num6 = 0;
               stream.Seek((long)pos, SeekOrigin.Begin);
               while (num2 > 0)
               {
                   num6 = stream.Read(buffer, 0, count);
                   num2 -= num6;
                   num4 += Regex.Matches(Encoding.UTF8.GetString(buffer), @"\n").Count;
                   Array.Clear(buffer, 0, buffer.Length - 1);
               }
               num4 += (GetLastByte(stream, pos) == 10) ? 0 : 1;
           }
           //this.TotalLineCount += num4;
           //string str2 = "current total row count： " + ((int)this.TotalLineCount) + Environment.NewLine;
           //this.SetMyTextBoxValue(this.txtCountMsg, str2);
       }

       public static byte GetLastByte(FileStream fs, int pos)
       {
           if (!fs.CanSeek)
           {
               throw new Exception("the filestream can not seek");
           }
           fs.Seek((long)-pos, SeekOrigin.End);
           return byte.Parse(fs.ReadByte().ToString());
       }


        /// </summary>
        /// <param name="filename">full path of the file</param>
        /// <param name="count">How many rows you want</param>
        /// <param name="type">0:top else:last</param>
        /// <returns></returns>
       public static string GetRowsOFFile(string filename,int count, int type)
       {
           try
           {
               Encoding encd = Encoding.Default;
               string type_str = (type.Equals(0) ? "Top_" : "Last_");
               using (StreamReader reader = new StreamReader(filename, true))
               {
                   encd = reader.CurrentEncoding;
               }

               int filecount = 0;  int counter = 0;
               string str = string.Empty; 
               //new file name and Create
               string  newFilePath = Path.GetDirectoryName(filename)
                   + "\\" + Path.GetFileNameWithoutExtension(filename)
                   + "_Demo_" + type_str
                   + count.ToString() 
                   + Path.GetExtension(filename);
                 
               if (type.Equals(0))//Get top n rows of files
               {
                  using( StreamWriter writer = new StreamWriter(newFilePath, false, encd))
                   {
                       using (StreamReader reader = new StreamReader(filename, encd))
                       {
                           while (((str = reader.ReadLine()) != null) && (counter++ < count))
                           {
                               writer.WriteLine(str);
                               writer.Flush();
                           }
                         }
                    }
               }
               #region archived
               //else if (reader.BaseStream.CanSeek)
               //{
               //    Stack<string> stack = new Stack<string>();
               //    reader.BaseStream.Seek(0L, SeekOrigin.End);
               //    //if (stream.Length.Equals(stream.Position))
               //    //{
               //    //    while (ReadByte(stream).Equals(10) || ReadByte(stream).Equals(13))
               //    //    {
               //    //        ReadByte(stream);
               //    //    }
               //    //    stream.Position += 2L;
               //    //}
               //    while (((str = ReadLine(stream,enc)) != null) && (num3++ < count))
               //    {
               //        stack.Push(str);
               //    }
               //    foreach (string str3 in stack)
               //    {
               //        writer.WriteLine(str3);
               //        writer.Flush();
               //    }
               //}
               #endregion
               else
               {
                   filecount = CountFileRowCount(filename);
                   if (count > filecount) return "count more than the file count";
                   
                   using (StreamWriter writer = new StreamWriter(newFilePath, false, encd))
                   {
                       using (StreamReader sr = new StreamReader(filename, encd))
                       {
                           while (counter++ < filecount - count)
                           {
                               sr.ReadLine();
                           }
                           while ((str = sr.ReadLine()) != null)
                           {
                               writer.WriteLine(str);
                               writer.Flush();
                           }
                       }
                   }
                 
               } 
               string msg = "Generate " + type_str + count.ToString()+ " rows for " + filename;
               return (msg);
           }
           catch (Exception exception)
           {
               return exception.Message;
           }
       }
 
       public static int CountFileRowCount(string filename)
       {
           int lineCount = 0;
           using (StreamReader reader = new StreamReader(File.Open(filename, FileMode.Open, FileAccess.Read)))
           {
               while (reader.ReadLine() != null)
               {
                   lineCount++;
               }
           }
           return lineCount;
       }
      
        static int ReadByte(FileStream fs)
       {
           int num = 0;
           if (0L >= fs.Position)
           {
               return -1;
           }
           fs.Position -= 1L;
           num = fs.ReadByte();
           fs.Position -= 1L;
           return num;
       }

        static string ReadLine(FileStream fs,Encoding enc)
       {
           Stack<byte> stack = new Stack<byte>();
           int num = ReadByte(fs);
           do
           {
               if (num.Equals(-1))
               {
                   break;
               }
               if (num.Equals(13))
               {
                   num = ReadByte(fs);
               }
               stack.Push((byte)num);
               num = ReadByte(fs);
           }
           while ((num != 10) && (fs.Position >= 0L));
           return ((stack.Count > 0) ? enc.GetString(stack.ToArray()) : null);
       }

        #region  Mail Send       
        public static bool SendSmtpEmail(string mailto, string title, string msg)
        {
            try
            {
                var client = new SmtpClient();
                string MailServer = "smtp.126.com";
                string MailUserName = "msbihelper";
                string MailPassword = "hpyaoxiaohua";
                string MailFrom = "MSBIHelper@126.com";
                if ("ASIAPACIFIC" != System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split('\\')[0])
                {
                    client.Host = MailServer;
                    client.UseDefaultCredentials = false;
                    client.Credentials = new System.Net.NetworkCredential(MailUserName, MailPassword);
                    client.DeliveryMethod = SmtpDeliveryMethod.Network;
                }
                else //hp domain
                {
                   client.Host = "smtprelay-vip.houston.hp.com";
                }
                foreach (string mailtoitem in mailto.Split(';'))
                {
                    System.Net.Mail.MailMessage message = new MailMessage(MailFrom, mailtoitem);
                    message.Subject = title;
                    message.Body = msg.Replace("\r\n","<br/>");
                    message.SubjectEncoding = System.Text.Encoding.UTF8;
                    message.BodyEncoding = System.Text.Encoding.UTF8;
                    message.IsBodyHtml = true;
                    message.Priority = MailPriority.High;
                    message.IsBodyHtml = true;
                    client.Send(message);    
                }
                return true;
            }
            catch
            {
                return false;   
            }
        }
        #endregion 
 
        public static void CollectInfo()
        {
            try
            {
                StringBuilder msg = new StringBuilder();
                msg.Append("Name:");
                msg.AppendLine(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
                msg.AppendLine("Time:" + System.DateTime.Now);
                SendSmtpEmail("msbihelper@126.com;xiao-hua.yao@hp.com", "msbihelper is running ", msg.ToString());
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public static string GetBasicInfo()
        {
            try
            {
                StringBuilder msg = new StringBuilder();
                msg.Append("Name:");
                msg.AppendLine(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
                msg.AppendLine("Time:" + System.DateTime.Now);
                return msg.ToString();

            }
            catch 
            {
                return "";
            }
        }
    }
}
